using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Mbs.ComponentModel.Container.Context;
using Mbs.Reflection;

namespace Mbs.ComponentModel.Container.Injection
{
    public class FieldInspect : InspectAdapter<FieldInfo>
    {
        private const BindingFlags Flags = BindingFlags.SetField | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ;

        protected override IInjectContext<FieldInfo> DoExecute(IInspectContext ctx)
        {
            var items = (from f in ctx.Instance.GetType().GetFields(Flags)
                         let att = f.GetAttribute<InjectAttribute>(false)
                         let ignoreAtt = f.GetAttribute<IgnoreInjectAttribute>(false)
                         let id = att != null ? att.Id : string.Empty
                         where ignoreAtt == null && Filter(att, f)
                         select new KeyValuePair<FieldInfo, string>(f, id)
                       ).ToArray();

            return new InjectContext<FieldInfo>(Kernel, ctx.Component, ctx.Instance, items);
        }

        protected virtual bool Filter(InjectAttribute att, FieldInfo p)
        {
            if (att == null)
                return false;

            if (!string.IsNullOrEmpty(att.Id))
                return Kernel.HasRegister(att.Id);

            return Kernel.HasRegister(p.FieldType);
        }
    }
}
